home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gnu / adainc / s-secsta.adb < prev    next >
Text File  |  1996-01-30  |  10KB  |  282 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --               S Y S T E M . S E C O N D A R Y _ S T A C K                --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.21 $                             --
  10. --                                                                          --
  11. --           Copyright (c) 1992,1993,1994 NYU, All Rights Reserved          --
  12. --                                                                          --
  13. -- The GNAT library is free software; you can redistribute it and/or modify --
  14. -- it under terms of the GNU Library General Public License as published by --
  15. -- the Free Software  Foundation; either version 2, or (at your option) any --
  16. -- later version.  The GNAT library is distributed in the hope that it will --
  17. -- be useful, but WITHOUT ANY WARRANTY;  without even  the implied warranty --
  18. -- of MERCHANTABILITY  or  FITNESS FOR  A PARTICULAR PURPOSE.  See the  GNU --
  19. -- Library  General  Public  License for  more  details.  You  should  have --
  20. -- received  a copy of the GNU  Library  General Public License  along with --
  21. -- the GNAT library;  see the file  COPYING.LIB.  If not, write to the Free --
  22. -- Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.        --
  23. --                                                                          --
  24. ------------------------------------------------------------------------------
  25.  
  26. with System.Task_Specific_Data;
  27. with System.Tasking_Soft_Links;
  28. with Unchecked_Conversion;
  29. with Unchecked_Deallocation;
  30.  
  31. package body System.Secondary_Stack is
  32.  
  33.  
  34.  
  35.    --                                      +------------------+
  36.    --                                      |       Next       |
  37.    --                                      +------------------+
  38.    --                                      |                  | Last (200)
  39.    --                                      |                  |
  40.    --                                      |                  |
  41.    --                                      |                  |
  42.    --                                      |                  |
  43.    --                                      |                  |
  44.    --                                      |                  | First (101)
  45.    --                                      +------------------+
  46.    --                         +----------> |          |       |
  47.    --                         |            +----------+-------+
  48.    --                         |                    |  |
  49.    --                         |                    ^  V
  50.    --                         |                    |  |
  51.    --                         |            +-------+----------+
  52.    --                         |            |       |          |
  53.    --                         |            +------------------+
  54.    --                         |            |                  | Last (100)
  55.    --                         |            |         C        |
  56.    --                         |            |         H        |
  57.    --    +-----------------+  |  +-------->|         U        |
  58.    --    |  Current_Chunk -|--+  |         |         N        |
  59.    --    +-----------------+     |         |         K        |
  60.    --    |       Top      -|-----+         |                  | First (1)
  61.    --    +-----------------+               +------------------+
  62.    --    | Default_Size    |               |       Prev       |
  63.    --    +-----------------+               +------------------+
  64.    --
  65.    --
  66.  
  67.    type Memory is array (Mark_Id range <>) of Storage_Element;
  68.  
  69.    type Chunk_Id (First, Last : Mark_Id);
  70.    type Chunk_Ptr is access Chunk_Id;
  71.  
  72.    type Chunk_Id (First, Last : Mark_Id) is record
  73.       Prev, Next : Chunk_Ptr;
  74.       Mem        : Memory (First .. Last);
  75.    end record;
  76.  
  77.    type Stack_Id is record
  78.       Top           : Mark_Id;
  79.       Current_Chunk : Chunk_Ptr;
  80.       Default_Size  : Storage_Count;
  81.    end record;
  82.  
  83.    type Stack_Ptr is access Stack_Id;
  84.  
  85.    function From_Addr is new Unchecked_Conversion (Address, Stack_Ptr);
  86.    function To_Addr   is new Unchecked_Conversion (Stack_Ptr, System.Address);
  87.  
  88.    ------------------
  89.    -- Storage_Size --
  90.    ------------------
  91.  
  92.    function Storage_Size (Pool : Secondary_Stack_Pool) return Storage_Count is
  93.       Stack : constant Stack_Ptr
  94.         := From_Addr (System.Task_Specific_Data.Get_Sec_Stack_Addr);
  95.       Chunk : Chunk_Ptr := Stack.Current_Chunk;
  96.  
  97.    begin
  98.       while Chunk.Next /= null loop
  99.          Chunk := Chunk.Next;
  100.       end loop;
  101.  
  102.       return Storage_Count (Chunk.Last);
  103.    end Storage_Size;
  104.  
  105.    --------------
  106.    -- Allocate --
  107.    --------------
  108.  
  109.    procedure Allocate
  110.      (Pool         : in out Secondary_Stack_Pool;
  111.       Address      :    out System.Address;
  112.       Storage_Size : in     Storage_Count;
  113.       Alignment    : in     Storage_Count)
  114.    is
  115.       Stack : constant Stack_Ptr
  116.         := From_Addr (System.Task_Specific_Data.Get_Sec_Stack_Addr);
  117.       Chunk : Chunk_Ptr := Stack.Current_Chunk;
  118.  
  119.    begin
  120.       --  The Current_Chunk may not be the good one if a lot of release
  121.       --  operations have taken place. So go down the stack if necessary
  122.  
  123.       while  Chunk.First > Stack.Top loop
  124.          Chunk := Chunk.Prev;
  125.       end loop;
  126.  
  127.       --  Find out if the available memory in the current chunk is sufficient.
  128.       --  if not, go to the next one and eventally create the necessary room
  129.  
  130.       while Chunk.Last - Stack.Top + 1 < Mark_Id (Storage_Size) loop
  131.          if Chunk.Next /= null then
  132.             Chunk := Chunk.Next;
  133.  
  134.          --  Create new chunk of the default size unless it is not sufficient
  135.  
  136.          elsif Storage_Size <= Stack.Default_Size then
  137.             Chunk.Next := new Chunk_Id (
  138.               First => Chunk.Last + 1,
  139.               Last => Chunk.Last + Mark_Id (Stack.Default_Size));
  140.  
  141.             Chunk.Next.Prev := Chunk;
  142.  
  143.          else
  144.             Chunk.Next := new Chunk_Id (
  145.               First => Chunk.Last + 1,
  146.               Last  => Chunk.Last + Mark_Id (Storage_Size));
  147.  
  148.             Chunk.Next.Prev := Chunk;
  149.          end if;
  150.  
  151.          Stack.Top := Chunk.First;
  152.       end loop;
  153.  
  154.       --  Resulting address is the address pointed by Stack.Top
  155.  
  156.       Address             := Chunk.Mem (Stack.Top)'Address;
  157.       Stack.Top           := Stack.Top + Mark_Id (Storage_Size);
  158.       Stack.Current_Chunk := Chunk;
  159.    end Allocate;
  160.  
  161.    ----------------
  162.    -- Deallocate --
  163.    ----------------
  164.  
  165.    --  Nothing to do, since space is released by an unmark operation
  166.  
  167.    procedure Deallocate
  168.      (Pool         : in out Secondary_Stack_Pool;
  169.       Address      : in     System.Address;
  170.       Storage_Size : in     Storage_Count;
  171.       Alignment    : in     Storage_Count)
  172.    is
  173.    begin
  174.       null;
  175.    end Deallocate;
  176.  
  177.    -------------
  178.    -- SS_Init --
  179.    -------------
  180.  
  181.    procedure SS_Init (Stk : out System.Address; Size : Natural) is
  182.       Stack : Stack_Ptr;
  183.  
  184.    begin
  185.       Stack               := new Stack_Id;
  186.       Stack.Current_Chunk := new Chunk_Id (1, Mark_Id (Size));
  187.       Stack.Top           := 1;
  188.       Stack.Default_Size  := Storage_Count (Size);
  189.  
  190.       Stk := To_Addr (Stack);
  191.    end SS_Init;
  192.  
  193.    -------------
  194.    -- SS_Free --
  195.    -------------
  196.  
  197.    procedure SS_Free (Stk : System.Address) is
  198.       Stack : Stack_Ptr := From_Addr (Stk);
  199.       Chunk : Chunk_Ptr := Stack.Current_Chunk;
  200.  
  201.       procedure Free is new Unchecked_Deallocation (Stack_Id, Stack_Ptr);
  202.       procedure Free is new Unchecked_Deallocation (Chunk_Id, Chunk_Ptr);
  203.  
  204.    begin
  205.       while Chunk.Prev /= null loop
  206.          Chunk := Chunk.Prev;
  207.       end loop;
  208.  
  209.       while Chunk.Next /= null loop
  210.          Chunk := Chunk.Next;
  211.          Free (Chunk.Prev);
  212.       end loop;
  213.  
  214.       Free (Chunk);
  215.       Free (Stack);
  216.    end SS_Free;
  217.  
  218.    -------------
  219.    -- SS_Mark --
  220.    -------------
  221.  
  222.    function SS_Mark return Mark_Id is
  223.    begin
  224.       return From_Addr (System.Task_Specific_Data.Get_Sec_Stack_Addr).Top;
  225.    end SS_Mark;
  226.  
  227.    ----------------
  228.    -- SS_Release --
  229.    ----------------
  230.  
  231.    procedure SS_Release (M : Mark_Id) is
  232.    begin
  233.       From_Addr (System.Task_Specific_Data.Get_Sec_Stack_Addr).Top := M;
  234.    end SS_Release;
  235.  
  236.    -------------
  237.    -- SS_Info --
  238.    -------------
  239.  
  240.    procedure SS_Info is
  241.       Stack     : constant Stack_Ptr
  242.         := From_Addr (System.Task_Specific_Data.Get_Sec_Stack_Addr);
  243.       Nb_Chunks : Integer            := 1;
  244.       Chunk     : Chunk_Ptr          := Stack.Current_Chunk;
  245.  
  246.    begin
  247.       Put_Line ("Secondary Stack information:");
  248.  
  249.       while Chunk.Prev /= null loop
  250.          Chunk := Chunk.Prev;
  251.       end loop;
  252.  
  253.       while Chunk.Next /= null loop
  254.          Nb_Chunks := Nb_Chunks + 1;
  255.          Chunk := Chunk.Next;
  256.       end loop;
  257.  
  258.       --  Current Chunk information
  259.  
  260.       Put_Line (
  261.         "  Total size              : "
  262.         & Mark_Id'Image (Chunk.Last)
  263.         & " bytes");
  264.       Put_Line (
  265.         "  Current allocated space : "
  266.         & Mark_Id'Image (Stack.Top - 1)
  267.         & " bytes");
  268.  
  269.       Put_Line (
  270.         "  Number of Chunks       : "
  271.         & Integer'Image (Nb_Chunks));
  272.  
  273.       Put_Line (
  274.         "  Default size of Chunks : "
  275.         & Storage_Count'Image (Stack.Default_Size));
  276.    end SS_Info;
  277. begin
  278.    System.Tasking_Soft_Links.SS_Init := SS_Init'Access;
  279.    System.Tasking_Soft_Links.SS_Free := SS_Free'Access;
  280.  
  281. end System.Secondary_Stack;
  282.